package com.lemon.cloud.exception;

import com.lemon.cloud.command.Command;
import com.lemon.cloud.representation.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * DefaultExceptionHandler
 *
 * @author Frank Zhang
 * @date 2019-01-08 9:51 AM
 */
@Slf4j
@Component
public class DefaultExceptionHandler implements ExceptionHandler {

    public static DefaultExceptionHandler singleton = new DefaultExceptionHandler();

    /**
     * @param command
     * @param response
     * @param exception
     * @return void
     * @description
     * @author lemon
     * @date 2019-09-15 17:13
     */
    @Override
    public void handleException(Command command, Response response, Exception exception) {
        buildResponse(response, exception);
        printLog(command, response, exception);
    }

    /**
     * @param command
     * @param response
     * @param throwable
     * @return void
     * @description
     * @author lemon
     * @date 2019-09-15 17:13
     */
    @Override
    public void handleThrowable(Command command, Response response, Throwable throwable) {
        buildResponse(response, throwable);
        printLog(command, response, throwable);
    }

    /**
     * @param response
     * @param throwable
     * @return void
     * @description
     * @author lemon
     * @date 2019-09-15 17:14
     */
    private void buildResponse(Response response, Throwable throwable) {
        if (throwable instanceof BasicException) {
            ErrorCode errCode = ((BasicException) throwable).getErrCode();
            response.setCode(errCode.getErrCode());
        } else {
            response.setCode(BasicErrorCode.SYS_ERROR.getErrCode());
        }

        response.setMessage(throwable.getMessage());
        response.setSuccess(false);
    }

    /**
     * @param cmd
     * @param response
     * @param throwable
     * @return void
     * @description
     * @author lemon
     * @date 2019-09-15 17:14
     */
    private void printLog(Command cmd, Response response, Throwable throwable) {
        if (throwable instanceof BasicException) {
            // biz exception is expected, only warn it
            log.warn(buildErrorMsg(cmd, response));
        } else {
            // sys exception should be monitored, and pay attention to it
            log.error(buildErrorMsg(cmd, response), throwable);
        }
    }

    /**
     * @param cmd
     * @param response
     * @return java.lang.String
     * @description
     * @author lemon
     * @date 2019-09-15 17:14
     */
    private String buildErrorMsg(Command cmd, Response response) {
        return "Process [" + cmd + "] failed, errorCode: " + response.getCode() + " errorMsg:" + response.getMessage();
    }
}
